define([], function() {

    return new function(p) { this.__proto__ = p; } ({

        path : window.location.pathname,
        emulate: !(window.history && window.history.replaceState && window.history.pushState),
        history: new Array(),

        init : function() {
            $(window).bind("popstate", this, function(e) {
                e.data.popState(e);
            });
        },

        getPath : function() {
            var path = this.path.split("/");
            for (var i = 0; i < path.length; i = i + 1) {
                if (path[i] === "") {
                    path.splice(i, 1);
                }
            }
            return path;
        },

        getFirst : function() {
            var path = this.getPath();
            return path.length > 0 && path[0].length > 0 ? path[0] : "home";
        },

        getSecond : function() {
            var path = this.getPath();
            return path.length > 1 ? path[1] : null;
        },

        getThird : function() {
            var path = this.getPath();
            return path.length > 2 ? path[2] : null;
        },

        popState : function(e) {
            var state = this.emulate && this.history.length > 0 ? this.history.pop() : null;
            if (state) {
                e.stopPropagation();
            } else {
                state = e.target.event.state;
                if (this.history.length > 0) {
                    this.history.pop();
                }
            }
            this.goToPage(state);
        },

        goToPage : function(state) {
            if (state instanceof Object && typeof state.path === "string") {
                this.path = state.path;
            } else {
                this.path = window.location.pathname;
            }
            var page = this.getSecond();
            require(["app/gnomus"], function(gnomus) {
                gnomus.changePageSmart(page);
            });
        },

        pushHistory : function(path) {
            var merchant = this.getFirst();
            var page = this.getSecond();
            if (path !== this.path) {
                var state = { path : path, hash : path};
                // no need to push /merchant => /merchant/page, just replace.
                if (this.path === ("/" + merchant)
                    && path === ("/" + merchant + "/" + page)) {
                    this.replaceState(state, page, path);
                } else {
                    // state.hash needs to be set to prevent jqm.transitionHandlers from throwing errors
                    this.pushState(state, page, path);
                }
            }
        },

        replaceState : function(state, page, path) {
            if (!this.emulate) {
                try { window.history.replaceState(state, page, path);
                } catch (e) { alert("replaceState failed " + e);
                }
            }
            if (this.history.length > 0) {
                this.history[this.history.length - 1] = { state: state, page: page, path: path };
            } else {
                this.history.push({ state: state, page: page, path: path });
            }
            this.path = path;
        },

        pushState : function(state, page, path) {
            if (!this.emulate) {
                try { window.history.pushState(state, page, path);
                } catch (e) { alert("replaceState failed " + e);
                }
            }
            this.history.push({ state: state, page: page, path: path });
            this.path = path;
        },

        back : function() {
            if (this.emulate) {
                if (this.history.length > 1) {
                    this.history.pop(); /* pop current page */
                    this.goToPage(this.history.pop());
                } else {
                    alert("calling url.back when history is empty");
                }
            } else {
                window.history.back()
            }
        }
    });
});
